1 Learning Outcomes

2 Motivation

3 Basic Layouts

3.1 Add a Title using titlePanel()

```r
library(shiny)

ui <- fluidPage(
    titlePanel("My First Title", windowTitle = "I am the Window Title")
)

server <- function(input, output) {

}

shinyApp(ui = ui, server = server)
```
  • Running the app, you should get something like this:

     

4 Create a Sidebar Layout using sidebarLayout()

4.1 Example: Create an app with a Sidebar Layout to plot random normal draws:

  • Use a slider to get the number of observations
  • Output a histogram

    library(shiny)
    library(ggplot2)
    
    ui <- fluidPage(
      titlePanel("Random Normal Histogram"),
      sidebarLayout(
        sidebarPanel(
          sliderInput("nobs", "Number of Observations", min = 1, max = 500, value = 100)
        ),
        mainPanel(
          plotOutput("hist")
        )
      )
    )
    
    server <- function(input, output) {
      output$hist <- renderPlot({
        rout <- data.frame(x = rnorm(n = input$nobs))
        ggplot(rout, aes(x = x)) +
          geom_histogram(bins = 30) +
          theme_bw()
      })
    }
    
    shinyApp(ui = ui, server = server)
  • Running the app, you should get something like this (side by side - not top to bottom):

     

4.2 sidebarPanelLayout() Details

  • sidebarPanel():
    • An argument of sidebarLayout().
    • It can have arguments for input controls (elements), e.g., sliderInput(), textInput(), etc.
    • Include multiple input elements by separating them, as function arguments, with a comma.
  • mainPanel():
    • An argument of sidebarLayout().
    • It can have arguments for output controls (elements), e.g. plotOutput(), textOutput(), etc.
    • Include multiple output elements by separating them, as function arguments, with a comma.
  • Hadley’s Graphic:

     

  • You can put input elements in mainPanel() and output elements in sidebarPanel() and the app won’t die.
    • UX or UI design is its own specialty .

4.3 Exercise:

  • Create a Shiny app with the sidebar layout. The inputs should be the number of bins, the plot title, and which variable to plot from mtcars. The output should be a histogram. Add a nice shiny app title.

    Your final Shiny App should look like this:

     

5 Create a fluidPage() Grid Layout with fluidRow() and column().

5.1 Example with fluidRow() and column()

  • Let’s make a shiny app to plot two variables from mtcars with two rows of panels
    • First row: two input columns: one with two inputs (variable selections) and one with one (number of bins)
    • Second Row: three output columns: each with one pol: a point plot and two histograms.

      library(shiny)
      library(ggplot2)
      
      ui <- fluidPage(
        fluidRow(title = "Inputs",
                 column(6,
                        varSelectInput("var1", "Variable 1", data = mtcars),
                        varSelectInput("var2", "Variable 2", data = mtcars)
                 ),
                 column(6,
                        sliderInput("bins", "Number of Bins", min = 1, max = 50, value = 20)
                 )
        ),
        fluidRow(title = "Outputs",
                 column(4,
                        plotOutput("plot1")
                 ),
                 column(4,
                        plotOutput("plot2")
                 ),
                 column(4,
                        plotOutput("plot3")
                 )
        )
      )
      
      server <- function(input, output) {
        output$plot1 <- renderPlot({
          ggplot(mtcars, aes(x = !!input$var1, y = !!input$var2)) +
            geom_point()
        })
      
        output$plot2 <- renderPlot({
          ggplot(mtcars, aes(x = !!input$var1)) +
            geom_histogram(bins = input$bins)
        })
      
        output$plot3 <- renderPlot({
          ggplot(mtcars, aes(x = !!input$var2)) +
            geom_histogram(bins = input$bins)
        })
      }
      
      shinyApp(ui = ui, server = server)
  • Running the app, you should get something like this:

     

  • Note: You can nest fluidRow()s inside fluidRow()s so it can get quite complicated.

5.2 Exercise:

  • Create a grid layout of four squares where the top left square takes as input two variables of the iris dataset to include in a scatterplot and the bottom right contains the resulting scatterplot, color-coded by species. The top right square and bottom left squares should remain empty. Have the second variable default to Sepal.Width.

    • Your final app should look like this:

       

6 Creating sets of Tabs with tabsetPanel() and tabPanel()

6.1 tabsetPanel()

- Arguments include calls to `tabPanel()` calls.
- You place it as an argument in either `mainPanel()` in the sidebar layout,
  or in one of the `column()` calls in the grid layout.

6.2 tabPanel()

- Takes as input different input/output elements, separated by a comma.
- Each element will get its own tab.
- Needs to be placed in `tabsetPanel()`.

6.3 Example

  • Here is an example from the mtcars dataset, where the tabs have different plots for the variables we select.

    library(shiny)
    library(ggplot2)
    
    ui <- fluidPage(
      sidebarLayout(
        sidebarPanel(
          varSelectInput("var1", "Variable 1", data = mtcars),
          varSelectInput("var2", "Variable 2", data = mtcars),
          sliderInput("bins", "Number of Bins", min = 1, max = 50, value = 20)
        ),
        mainPanel(
          tabsetPanel(
            tabPanel("Scatterplot",
                     plotOutput("plot1")
            ),
            tabPanel("Histogram of Variable 1",
                     plotOutput("plot2")
            ),
            tabPanel("Histogram of Variable 2",
                     plotOutput("plot3")
            )
          )
        )
      )
    )
    
    server <- function(input, output) {
      output$plot1 <- renderPlot({
        ggplot(mtcars, aes(x = !!input$var1, y = !!input$var2)) +
          geom_point()
      })
    
      output$plot2 <- renderPlot({
        ggplot(mtcars, aes(x = !!input$var1)) +
          geom_histogram(bins = input$bins)
      })
    
      output$plot3 <- renderPlot({
        ggplot(mtcars, aes(x = !!input$var2)) +
          geom_histogram(bins = input$bins)
      })
    }
    
    shinyApp(ui = ui, server = server)
  • Running the app, you should get something like this:

     

6.4 Exercise:

  • Create a basic Shiny app with a tab for a density plot, a histogram, and a boxplot for a variable from the iris dataset.
    • The user should get to choose the variable plotted, the number of bins for the histogram, and the bandwidth for the density plot (see the help page of geom_smooth()).
    • A good default value for the bandwidth might be 0.25 in this case.

      Your app should look like this:

       

7 Grouping Elements

7.1 Use wellPanel() to group elements together in a slightly inset border.

  • wellPanel()

    library(shiny)
    library(ggplot2)
    
    ui <- fluidPage(
      wellPanel(
        sliderInput("bins", "How many bins?", min = 1, max = 50, value = 20),
        plotOutput("hist")
      )
    )
    
    server <- function(input, output, session) {
      output$hist <- renderPlot({
        ggplot(mtcars, aes(x = mpg)) +
          geom_histogram(bins = input$bins)
      })
    }
    
    shinyApp(ui, server)

     

7.2 Other Panels

  • There are many other visual styles for groupings.
  • Here are some other panels for grouping elements together.
    • absolutePanel().
    • conditionalPanel().
    • fixedPanel().
    • headerPanel().
    • inputPanel().
    • navlistPanel().

8 Shiny Themes with shinytheme("theme_name")

8.1 Call for themes inside fluidPage()

  • Inside fluidPage(), list the theme argument to be shinytheme("theme_name"), where "theme_name" is one of the themes that comes with shinythemes.

  • The full list of available themes can be found by

    help("shinythemes")
  • Example:

    library(shiny)
    library(shinythemes)
    
    ui <- fluidPage(theme = shinytheme("darkly"),
                    sidebarLayout(
                      sidebarPanel(
                        sliderInput("number", "select a number", 0, 100, 40)
                        ), 
                      mainPanel(
                        tabsetPanel(
                          tabPanel("a"),
                          tabPanel("b"),
                          tabPanel("c")
                          )
                        )
                    )
    )
    
    server <- function(input, output, session) {
    
    }
    
    shinyApp(ui, server)

     

8.2 Customizing Shiny Themes with the “fresh” package

  • The fresh R package provides a lot of customization of the Bootstrap and Bootswatch, which Shiny uses for its appearance.

    library(fresh)
  • To use the fresh package, you need to use it in an app.R file for a Shiny App
    • it won’t work inline in an R Markdown document.

8.2.1 Place customizations in a create_theme() call.

  • create_theme() arguments you should use:

    • theme: What theme do you wish to customize? Say "default" for the default Shiny theme.
      • Otherwise, say one of the themes from the shinythemes package — help("shinythemes").
    • output_file: The location to put the customized formatting file. This should end with “.css” since it will be a CSS file.

    • You must place the output file in a “www” sub-directory of your Shiny App.

    • Every other argument starts with bs_vars_*().
      • For example, bs_vars_global() adjusts the global environment of the Shiny App (default text color, background color, the presence of a border, etc).
      create_theme(
          theme = "default",
          bs_vars_color(
              gray_base = "#354e5c",
          ),
          bs_vars_wells(
              bg = "#FFF",
              border = "#3f2d54"
          ),
          bs_vars_global(
            body_bg = "#e5ffe5"
          ),
          output_file = "www/mytheme.css"
      )
  • You can get those hexadecimal colors by either googling “color wheel” or looking up the common web colors: http://websafecolors.info/color-chart

  • In fluidPage(), you then give the theme argument the path to the CSS file.
    • You don’t need to say “www/mytheme.css” since Shiny will make the contents of the www directory available in the working directory.

      ui <- fluidPage(
          theme = "mytheme.css",
          ...
      )

8.3 Example of changing the background colors

  • Copy and paste into an app.R file
library(shiny)
library(shinythemes)
library(fresh)
library(ggplot2)

create_theme(
  theme = "default",
  bs_vars_color(
    gray_base = "#354e5c"
  ),
  bs_vars_wells(
    bg = "#90ee90",
    border = "#552D42"
  ),
  bs_vars_global(
    body_bg = "#e5ffe5"
  ),
  bs_vars_input(
    color = "#5d3954",
    border_radius="20px"
  ),
  #
  output_file = "www/mytheme.css"
)

ui <- fluidPage(
  theme = "mytheme.css",
  titlePanel("Old Faithful Geyser Data"),
  sidebarLayout(
    sidebarPanel(
     wellPanel("This is a well Panel",
      textInput("plot_title", "Plot Title?", value = "Your Title"),
       sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
     )
       ),
    mainPanel(
      plotOutput("distPlot")
    )
  )
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    ggplot(faithful, aes(x = waiting)) +
      geom_histogram(bins = input$bins, fill = "palegreen4") +
      theme(plot.background = element_rect(fill = "palegreen1"))+
      ggtitle(input$plot_title) +
      theme(
        panel.background = element_rect(fill = "palegreen1",
                                        colour = "palegreen1",
                                        size = 0.5, linetype = "solid"),
        panel.grid.major = element_line(size = 0.5, linetype = 'solid',
                                        colour = "white"),
        panel.grid.minor = element_line(size = 0.25, linetype = 'solid',
                                        colour = "white")
      )
  })
}

shinyApp(ui = ui, server = server)
  • Inline  
  • As app

 

8.4 Exercise:

  • Change the default font in the above app to "Times New Roman".
    • You’ll need to scroll through the available functions library(help = "fresh").